using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using backend.Models.Dtos;
using backend.Repositories;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Services;

namespace backend.Controllers
{
    [EnableCors]
    [ApiController]
    [Route("api/info")]
    public class InfoController : ControllerBase
    {
        private readonly ZoneRepo _zoneRepo;
        private readonly ProfessionRepo _professionRepo;
        private readonly FailureRepo _failureRepo;

        public InfoController(ZoneRepo zoneRepo, ProfessionRepo professionRepo, FailureRepo failureRepo)
        {
            _zoneRepo = zoneRepo;
            _professionRepo = professionRepo;
            _failureRepo = failureRepo;
        }

        // only admin
        [HttpPost]
        public async Task<IActionResult> Post([FromBody] InfoDto infoDto)
        {
            var principal = JwtHelper.GetAndValidateJwtToken(Request);
            if (principal == null)
            {
                return StatusCode(401, new { code = "failure", description = "Unauthorized" });
            }
            if (principal.Role != "2")
            {
                return StatusCode(403, new { code = "failure", description = "Forbidden" });
            }
            if (infoDto == null || string.IsNullOrEmpty(infoDto.Type) || string.IsNullOrEmpty(infoDto.InfoID))
                return StatusCode((int)HttpStatusCode.BadRequest, new { code = "failure", descirption = "do not provide any type or value" });
            if (!IsValidatedInfoID(infoDto.InfoID))
                return StatusCode((int)HttpStatusCode.BadRequest, new { code = "failure", descirption = "InfoID should be fully uppercase" });
            try
            {
                switch (infoDto.Type.ToLower())
                {
                    case "location":
                        if (!string.IsNullOrEmpty(infoDto.NewArea))
                        {
                            await _zoneRepo.CreateFirstClassAsync(infoDto.InfoID, infoDto.NewArea);
                            return StatusCode((int)HttpStatusCode.Created, new { code = "success" });
                        }
                        else if (!string.IsNullOrEmpty(infoDto.NewLocation) && !string.IsNullOrEmpty(infoDto.Area))
                        {
                            await _zoneRepo.CreateSecondClassAsync(infoDto.InfoID, infoDto.NewLocation, infoDto.Area);
                            return StatusCode((int)HttpStatusCode.Created, new { code = "success" });
                        }
                        break;
                    case "job":
                        if (!string.IsNullOrEmpty(infoDto.NewJob))
                        {
                            await _professionRepo.CreateProfessionAsync(infoDto.InfoID, infoDto.NewJob);
                            return StatusCode((int)HttpStatusCode.Created, new { code = "success" });
                        }
                        break;
                    case "fault":
                        if (!string.IsNullOrEmpty(infoDto.NewFault) && !string.IsNullOrEmpty(infoDto.FaultHandledBy))
                        {
                            await _failureRepo.CreateFailureAsync(infoDto.InfoID, infoDto.NewFault, infoDto.FaultHandledBy);
                            return StatusCode((int)HttpStatusCode.Created, new { code = "success" });
                        }
                        break;
                    default:
                        return StatusCode((int)HttpStatusCode.NotImplemented, new { code = "failure", descirption = "field value does not match any supported type" });

                }

                return StatusCode((int)HttpStatusCode.BadRequest, new { code = "failure", descirption = "type provided, but no proper value provided" });
            }
            catch (Exception ex)
            {
                // Log the exception here
                return StatusCode((int)HttpStatusCode.InternalServerError, new { code = "failure", descirption = ex.Message });
            }
        }

        // only admin
        [HttpDelete]
        public async Task<IActionResult> Delete([FromBody] DeleteInfoDto deleteInfoDto)
        {
            var principal = JwtHelper.GetAndValidateJwtToken(Request);
            if (principal == null)
            {
                return StatusCode(401, new { code = "failure", description = "Unauthorized" });
            }
            if (principal.Role != "2")
            {
                return StatusCode(403, new { code = "failure", description = "Forbidden" });
            }
            if (deleteInfoDto == null || string.IsNullOrEmpty(deleteInfoDto.Type))
                return StatusCode((int)HttpStatusCode.BadRequest, new { code = "failure", description = "do not provide any type or value" });
            try
            {

                bool result;
                switch (deleteInfoDto.Type.ToLower())
                {
                    case "location":
                        if (!string.IsNullOrEmpty(deleteInfoDto.Area) && !string.IsNullOrEmpty(deleteInfoDto.Location))
                        {
                            // Delete a specific location within an area
                            result = await _zoneRepo.DeleteSecondClassAsync(deleteInfoDto.Location);
                            if (result)
                            {
                                return StatusCode((int)HttpStatusCode.OK, new { code = "success" });
                            }
                        }
                        else if (!string.IsNullOrEmpty(deleteInfoDto.Area))
                        {
                            // Delete an entire area
                            result = await _zoneRepo.DeleteFirstClassAsync(deleteInfoDto.Area);
                            if (result)
                            {

                                return StatusCode((int)HttpStatusCode.OK, new { code = "success" });
                            }
                        }
                        break;
                    case "job":
                        if (!string.IsNullOrEmpty(deleteInfoDto.Job))
                        {
                            // Delete a job
                            result = await _professionRepo.DeleteProfessionAsync(deleteInfoDto.Job);
                            if (result)
                            {
                                return StatusCode((int)HttpStatusCode.OK, new { code = "success" });
                            }
                        }
                        break;
                    case "fault":
                        if (!string.IsNullOrEmpty(deleteInfoDto.Fault))
                        {
                            // Delete a fault
                            result = await _failureRepo.DeleteFailureAsync(deleteInfoDto.Fault);
                            if (result)
                            {
                                return StatusCode((int)HttpStatusCode.OK, new { code = "success" });
                            }
                        }
                        break;
                    default:
                        return StatusCode((int)HttpStatusCode.NotImplemented, new { code = "failure", description = "field value does not match any supported type" });
                }

                return StatusCode((int)HttpStatusCode.BadRequest, new { code = "failure", description = "type provided, but no proper value provided" });
            }
            catch (Exception ex)
            {
                // Log the exception here
                return StatusCode((int)HttpStatusCode.InternalServerError, new { code = "failure", description = ex.Message });
            }
        }

        [HttpGet("{type}")]
        public async Task<IActionResult> GetInfoAsync(string type)
        {
            var principal = JwtHelper.GetAndValidateJwtToken(Request);
            if (principal == null)
            {
                return StatusCode(401, new { code = "failure", description = "Unauthorized" });
            }
            // 检查类型参数是否为空或无效
            if (string.IsNullOrWhiteSpace(type))
            {
                return BadRequest("Type parameter is required.");
            }

            type = type.ToLowerInvariant(); // 转换为小写以进行不区分大小写的比较

            switch (type)
            {
                case "location":
                    try
                    {
                        var locations = await _zoneRepo.GetZonesAsync();
                        return Ok(new { code = "success", data = locations });
                    }
                    catch (Exception ex)
                    {
                        return StatusCode(500, new { code = "error", message = "Failed to retrieve locations.", exception = ex.Message });
                    }

                case "job":
                    try
                    {
                        var jobs = await _professionRepo.GetProfessionsAsync();
                        return Ok(new { code = "success", data = jobs });
                    }
                    catch (Exception ex)
                    {
                        return StatusCode(500, new { code = "error", message = "Failed to retrieve jobs.", exception = ex.Message });
                    }

                case "faults":
                    try
                    {
                        var failures = await _failureRepo.GetFailuresAsync();
                        return Ok(new { code = "success", data = failures });
                    }
                    catch (Exception ex)
                    {
                        return StatusCode(500, new { code = "error", message = "Failed to retrieve failures.", exception = ex.Message });
                    }

                default:
                    return BadRequest(new { code = "error", message = "Invalid type parameter." });
            }
        }

        public static bool IsValidatedInfoID(string input)
        {
            return Regex.IsMatch(input, @"^[A-Z0-9-]*$");
        }
    }
}